/*
 * These files are distributed under the terms of the GNU GPLv2, the GNU General
 * Public version 2. See LICENSE.txt
 */
package fileCommodore;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;

import javax.swing.*;
import javax.swing.filechooser.*;

import org.apache.commons.vfs.*;

import fileCommodore.model.*;
import fileCommodore.plugin.*;
import fileCommodore.plugin.basicNavigation.*;
import fileCommodore.plugin.copy.*;
import fileCommodore.plugin.delete.*;
import fileCommodore.plugin.directoryCreator.*;
import fileCommodore.plugin.dos_shell.*;
import fileCommodore.plugin.externalEditor.*;
import fileCommodore.plugin.file_info.*;
import fileCommodore.plugin.hotpath.*;
import fileCommodore.plugin.launcher.*;
import fileCommodore.plugin.move.*;
import fileCommodore.plugin.pathChanger.*;
import fileCommodore.plugin.pathCloner.*;
import fileCommodore.plugin.pathHopper.*;
import fileCommodore.plugin.usermenu.*;
import fileCommodore.view.*;

/**
 * @author nado18@gmail.com, on Jul 13, 2007
 */
public class Main extends JFrame
{
	private static FileSystemManager fsm;
	private FilePane paneA;
	private FilePane paneB;
	private PathHopperPlugin hopperA = new PathHopperPlugin();
	private PathHopperPlugin hopperB = new PathHopperPlugin();
	private FileObjectTableModel modelA = new FileObjectTableModel();
	private FileObjectTableModel modelB = new FileObjectTableModel();
	private JSplitPane split;
	
	private FilePane active;
	private Vector<Plugin> plugins = new Vector<Plugin>();
	
	public void show(JPopupMenu menu)
	{
		getActivePane().show(menu);
	}
	
	public static boolean isMac()
	{
		return System.getProperty( "os.name" ).toLowerCase().contains( "mac" );
	}
	
	public static boolean isWindows()
	{
		return System.getProperty( "os.name" ).toLowerCase().contains(
			"windows" );
	}
	
	public static boolean isUnix()
	{
		return !( isMac() || isWindows() );
	}
	
	public Main()
	{
		super( "File Commodore" );
		try
		{
			fsm = VFS.getManager();
		}
		catch (FileSystemException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
		setLocationByPlatform( true );
		int pad = 5;
		
		// Create panes
		paneA = new FilePane( this, hopperA.getHopper(), modelA );
		paneB = new FilePane( this, hopperB.getHopper(), modelB );
		split = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, paneA, paneB );
		split.setBorder( BorderFactory.createEmptyBorder( pad, pad, pad, pad ) );
		setContentPane( split );
		
		Dimension ss = Toolkit.getDefaultToolkit().getScreenSize();
		setSize( 4 * ss.width / 5, 4 * ss.height / 5 );
		setLocationByPlatform(true);
		if( ! isMac() )
		{
			setExtendedState( JFrame.MAXIMIZED_BOTH );
		}
		
		initializePlugins();
		
		try
		{
			changeToDefaultDirectories();
		}
		catch (FileSystemException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		addWindowListener( new WindowAdapter()
		{
			@Override
			public void windowOpened( WindowEvent arg0 )
			{
				super.windowOpened( arg0 );
				split.setDividerLocation( 0.5 );
			}
		} );
		
		setVisible( true );
	}
	
	public void switchPanel( FilePane source )
	{
		if (source == paneA)
		{
			setActivePane( paneB );
		}
		else
		{
			setActivePane( paneA );
		}
	}
	
	private void setActivePane( FilePane fp )
	{
		active = fp;
		FilePane inactive = getInactivePane();
		
		active.focus();
		active.setActive( true );
		inactive.setActive( false );
		
		notifySelection( getInactivePane() );
		notifySelection( getActivePane() );
	}
	
	private FilePane getActivePane()
	{
		return active;
	}
	
	private FilePane getInactivePane()
	{
		FilePane inactive = getActivePane() == paneA ? paneB : paneA;
		
		return inactive;
	}
	
	private void setInactiveComponent( Component c )
	{
		int dividerLocation = split.getDividerLocation();
		
		if (active == paneA)
		{
			split.setBottomComponent( c );
		}
		else
		{
			split.setTopComponent( c );
		}
		
		split.setDividerLocation( dividerLocation );
		split.repaint();
	}
	
	public void showVisible( Visible v, boolean giveFocus )
	{
		JComponent c = v.getPluginComponent();
		setInactiveComponent( c );
		if (giveFocus)
		{
			c.requestFocus();
		}
	}
	
	public static void main( String[] args )
	{
		try
		{
			UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
		}
		catch (Exception ex)
		{
			ex.printStackTrace();
		}
		
		System.setProperty(
			"org.apache.commons.logging.Log",
			"org.apache.commons.logging.impl.SimpleLog" );
		System.setProperty(
			"org.apache.commons.logging.simplelog.defaultlog",
			"error" );
		
		Main m = new Main();
	}
	
	private void changeToDefaultDirectories() throws FileSystemException
	{
		switchPanel( paneB );
		
		File home = FileSystemView.getFileSystemView().getHomeDirectory();
		File root = new File( "/" );
		FileObject foHome = fsm.resolveFile( home.getAbsolutePath() );
		FileObject foRoot = fsm.resolveFile( root.getAbsolutePath() );
		changeActiveTo( foRoot );
		changeInactiveTo( foHome );
	}
	
	public void changeActiveTo( FileObject path ) throws FileSystemException
	{
		getActivePane().getModel().changeTo( path );
	}
	
	public void changeInactiveTo( FileObject path ) throws FileSystemException
	{
		getInactivePane().getModel().changeTo( path );
	}
	
	public FileObject resolve( String path ) throws FileSystemException
	{
		FileObject retval = fsm.resolveFile( path );
		return retval;
	}
	
	public boolean isVisible( VisiblePlugin visiblePlugin )
	{
		JComponent jc = visiblePlugin.getPluginComponent();
		boolean retval =
				( split.getTopComponent() == jc )
						|| ( split.getBottomComponent() == jc );
		return retval;
	}
	
	private void initializePlugins()
	{
		Plugin.setController( this );
		
		// TODO: Automatically discover plugins
		plugins.add( new DirectoryCreatorPlugin() );
		plugins.add( new DosShellPlugin() );
		plugins.add( new ExternalEditorPlugin() );
		plugins.add( new FileInfoPlugin() );
		plugins.add( new HotPathPlugin() );
		plugins.add( new LauncherPlugin() );
		plugins.add( new PathChangerPlugin() );
		plugins.add( new PathClonerPlugin() );
		plugins.add( new CopyPlugin() );
		plugins.add( new MovePlugin() );
		plugins.add( new DeletePlugin() );
		plugins.add( new BasicNavigationPlugin() );
		plugins.add( new UserMenuPlugin() );
		plugins.add( hopperA );
		plugins.add( hopperB );
		
		hopperA.setPane( paneA );
		hopperB.setPane( paneB );
	}
	
	public void notifyPlugins( KeyEvent e )
	{
		if (!e.isConsumed())
		{
			for (Plugin plugin : plugins)
			{
				plugin.handle( e );
			}
		}
	}
	
	public void notifySelection( FilePane filePane )
	{
		boolean isActive = getActivePane() == filePane;
		Selection selection = filePane.getSelection();
		if (isActive)
		{
			for (Plugin p : plugins)
			{
				p.setActiveSelection( selection );
				p.activeSelectionChanged();
			}
		}
		else
		{
			for (Plugin p : plugins)
			{
				p.setInactiveSelection( selection );
				p.inactiveSelectionChanged();
			}
		}
	}
	
	public static void mergeCopy( FileObject src, FileObject dstParent )
			throws FileSystemException
	{
		String srcName = src.getName().getBaseName();
		FileObject dst = dstParent.resolveFile( srcName );
		boolean done = false;
		
		if (dst.exists())
		{
			boolean isSrcFolder = FileType.FOLDER == src.getType();
			boolean isDstFolder = FileType.FOLDER == dst.getType();
			if (isSrcFolder && isDstFolder)
			{
				for (FileObject fo : src.getChildren())
				{
					mergeCopy( fo, dst );
				}
				done = true;
			}
		}
		
		if (!done)
		{
			dst.copyFrom( src, new AllFileSelector() );
		}
	}
	
	public static void mergeMove( FileObject src, FileObject dstParent )
			throws FileSystemException
	{
		String srcName = src.getName().getBaseName();
		FileObject dst = dstParent.resolveFile( srcName );
		boolean done = false;
		
		if (dst.exists())
		{
			boolean isSrcFolder = FileType.FOLDER == src.getType();
			boolean isDstFolder = FileType.FOLDER == dst.getType();
			if (isSrcFolder && isDstFolder)
			{
				for (FileObject fo : src.getChildren())
				{
					mergeMove( fo, dst );
				}
				src.delete();
				done = true;
			}
		}
		
		if (!done)
		{
			src.moveTo( dst );
		}
	}
}
